﻿Imports System.IO
Imports System.Text
Imports System.Text.RegularExpressions
Imports System.Xml.Serialization

Namespace Pop.Api.Parser

    ''' <summary>
    ''' POP XML响应通用解释器。
    ''' </summary>
    Public Class PopXmlParser(Of T As PopResponse)
        Implements IPopParser(Of T)

        Private Shared regex As New Regex("<(\w+?)[ >]", RegexOptions.Compiled)
        Private Shared parsers As New Dictionary(Of String, XmlSerializer)

#Region "IPopParser<T> Members"

        Public Function Parse(ByVal body As String) As T Implements IPopParser(Of T).Parse
            Dim serializer As XmlSerializer = Nothing
            Dim rootTagName As String = GetRootElement(body)

            Dim inc As Boolean = parsers.TryGetValue(rootTagName, serializer)
            If Not inc OrElse serializer Is Nothing Then
                Dim rootAttrs As New XmlAttributes()
                rootAttrs.XmlRoot = New XmlRootAttribute(rootTagName)

                Dim attrOvrs As New XmlAttributeOverrides()
                attrOvrs.Add(GetType(T), rootAttrs)

                serializer = New XmlSerializer(GetType(T), attrOvrs)
                parsers(rootTagName) = serializer
            End If

            Dim obj As Object = Nothing
            Using stream As Stream = New MemoryStream(Encoding.UTF8.GetBytes(body))
                obj = serializer.Deserialize(stream)
            End Using

            Dim rsp As T = DirectCast(obj, T)
            If rsp IsNot Nothing Then
                rsp.Body = body
            End If
            Return rsp
        End Function

#End Region

        ''' <summary>
        ''' 获取XML响应的根节点名称
        ''' </summary>
        Private Shared Function GetRootElement(ByVal body As String) As String
            Dim match As Match = regex.Match(body)
            If match.Success Then
                Return match.Groups(1).Value
            Else
                Throw New PopException("Invalid XML response format!")
            End If
        End Function

    End Class

End Namespace